home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / os2 / pmnos11s / lapb.c < prev    next >
C/C++ Source or Header  |  1993-07-30  |  22KB  |  830 lines

  1. /* Link Access Procedures Balanced (LAPB), the upper sublayer of
  2.  * AX.25 Level 2.
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  *
  5.  * 92/02/07 WG7J
  6.  * Modified to drop ax.25 route records in cases where routes
  7.  * were added by the connections. Inspired by K4TQL
  8.  */
  9. #include "global.h"
  10. #include "config.h"
  11. #ifdef AX25
  12. #include "mbuf.h"
  13. #include "timer.h"
  14. #include "ax25.h"
  15. #include "lapb.h"
  16. #include "ip.h"
  17. #include "netrom.h"
  18.  
  19. /* This forces data sent by jumpstarting a mailbox connect to
  20.  * resend the header etc. when the first UA reply is missed, and
  21.  * a second SABM is received for the same connection
  22.  * added by Ron Murray VK6ZJM, Murray_RJ@cc.curtin.edu.au
  23.  */
  24. #define SABM_HOLDOFF
  25.  
  26. static void handleit __ARGS((struct ax25_cb *axp,int pid,struct mbuf *bp));
  27. static void procdata __ARGS((struct ax25_cb *axp,struct mbuf *bp));
  28. static int ackours __ARGS((struct ax25_cb *axp,int16 n));
  29. static void clr_ex __ARGS((struct ax25_cb *axp));
  30. static void enq_resp __ARGS((struct ax25_cb *axp));
  31. static void inv_rex __ARGS((struct ax25_cb *axp));
  32.  
  33. /*needed for mailbox jumpstart - WG7J */
  34. #ifdef MAILBOX
  35. #ifdef NETROM
  36. extern struct nrnbr_tab *find_nrnbr __ARGS((char *, unsigned));
  37. #endif
  38. extern int Mbjumpstart;
  39. extern struct no_js *Exclude;
  40. #endif
  41.  
  42. /*If we have an AX.25 AUTO route record, drop it.*/
  43. static void
  44. drop_axr(axp)
  45. struct ax25_cb *axp;
  46. {
  47.     struct ax_route *axr;
  48.  
  49.     axr = ax_lookup(axp->remote);
  50.     if(axr != NULLAXR && axr->type != AX_LOCAL)
  51.         ax_drop(axp->remote);
  52.  
  53. }
  54.  
  55. /* Process incoming frames */
  56. int
  57. lapb_input(axp,cmdrsp,bp)
  58. struct ax25_cb *axp;        /* Link control structure */
  59. int cmdrsp;            /* Command/response flag */
  60. struct mbuf *bp;        /* Rest of frame, starting with ctl */
  61. {
  62.     int control;
  63.     int class;        /* General class (I/S/U) of frame */
  64.     int16 type;        /* Specific type (I/RR/RNR/etc) of frame */
  65.     char pf;        /* extracted poll/final bit */
  66.     char poll = 0;
  67.     char final = 0;
  68.     int16 nr;        /* ACK number of incoming frame */
  69.     int16 ns;        /* Seq number of incoming frame */
  70.     int16 tmp;
  71. #ifdef MAILBOX
  72. #ifdef NETROM
  73.     int ifnum;      /*used to find possible netrom connect*/
  74. #endif
  75.     struct no_js *ep;   /*scan the 'exclude-calls' list */
  76. #endif
  77.  
  78.     if(bp == NULLBUF || axp == NULLAX25){
  79.         free_p(bp);
  80.         return -1;
  81.     }
  82.  
  83.     /* Extract the various parts of the control field for easy use */
  84.     if((control = PULLCHAR(&bp)) == -1){
  85.         free_p(bp);    /* Probably not necessary */
  86.         return -1;
  87.     }
  88.     type = ftype(control);
  89.     class = type & 0x3;
  90.     pf = control & PF;
  91.     /* Check for polls and finals */
  92.     if(pf){
  93.         switch(cmdrsp){
  94.         case LAPB_COMMAND:
  95.             poll = YES;
  96.             break;
  97.         case LAPB_RESPONSE:
  98.             final = YES;
  99.             break;
  100.         }
  101.     }
  102.     /* Extract sequence numbers, if present */
  103.     switch(class){
  104.     case I:
  105.     case I+2:
  106.         ns = (control >> 1) & MMASK;
  107.     case S:    /* Note fall-thru */
  108.         nr = (control >> 5) & MMASK;
  109.         break;
  110.     }
  111.     /* This section follows the SDL diagrams by K3NA fairly closely */
  112.     switch(axp->state){
  113.     case LAPB_DISCONNECTED:
  114.         switch(type){
  115.         case SABM:    /* Initialize or reset link */
  116.             /* This a new incoming connection.
  117.              * Accept if we have enough memory left
  118.              * 920115 - WG7J
  119.              */
  120.             if(availmem() < Memthresh){
  121.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  122.                 break;
  123.             }
  124.             sendctl(axp,LAPB_RESPONSE,UA|pf);   /* Always accept */
  125.             clr_ex(axp);
  126.             axp->unack = axp->vr = axp->vs = 0;
  127.             lapbstate(axp,LAPB_CONNECTED);/* Resets state counters */
  128.             axp->srt = Axirtt;
  129.             axp->mdev = 0;
  130.             set_timer(&axp->t1,2*axp->srt);
  131.             start_timer(&axp->t3);
  132.             start_timer(&axp->t4);
  133. #ifdef SABM_HOLDOFF
  134.             axp->flags.rxd_I_frame = 0;    /* nothing received yet */
  135. #endif
  136.             /*Jump-start the mailbox. This causes the [NET-H$] prompt to
  137.              *be sent Immediately, instead of after the first data packet
  138.              *Check for connections from known netrom calls,
  139.              *calls from the 'jumpstart exclude' list and check if interface
  140.              *is in vc mode...
  141.              *we don't want to start the mailbox in these cases,
  142.              *since these could be attempts to do level 3 stuff.
  143.              *12/09/91 WG7J
  144.              */
  145. #ifdef MAILBOX
  146.             if(Mbjumpstart) {
  147. #ifdef NETROM
  148.                 if(axp->jumpstarted == NETROM_LINK) {
  149.                     /* check if the incoming interface is enabled for netrom*/
  150.                     for(ifnum = 0; ifnum < Nr_numiface; ifnum++)
  151.                         if(axp->iface == Nrifaces[ifnum].iface)
  152.                             break;
  153.                     if(ifnum != Nr_numiface)   /* A net/rom interface! */
  154.                         if(find_nrnbr(axp->remote,ifnum) != NULLNTAB)
  155.                             /* this is a netrom neighbour*/
  156.                             break;
  157.                 }
  158. #endif /* NETROM */
  159.                 /*Now check the 'exclude' list*/
  160.                 for(ep=Exclude;ep!=(struct no_js *)NULL;ep=ep->next)
  161.                     if(addreq(axp->remote,ep->call))
  162.                         break;
  163.                 if(ep != (struct no_js *)NULL) /*exclude this one*/
  164.                     break;
  165.  
  166.                 /*if the interface mode = VC, then DO NOT do it,
  167.                  * this could be a VC attempted by IP!
  168.                  */
  169.                 if(axp->iface->flags != CONNECT_MODE) {
  170.                     /*We passed all tests!*/
  171.                     axp->jumpstarted += JUMPSTARTED;
  172.                     s_arcall(axp,0);
  173.                 }
  174.             }
  175. #endif /* MAILBOX */
  176.             break;
  177.         case DISC:    /* Always answer a DISC with a DM */
  178.             sendctl(axp,LAPB_RESPONSE,DM|pf);
  179.             break;
  180.         case DM:    /* Ignore to avoid infinite loops */
  181.             break;
  182.         default:    /* All others get DM */
  183.             if(poll)
  184.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  185.             break;
  186.         }
  187.         if(axp->state == LAPB_DISCONNECTED){    /* we can close connection */
  188.             stop_timer(&axp->t1);    /* waste all the timers */
  189.             stop_timer(&axp->t3);
  190.             stop_timer(&axp->t4);
  191.             free_q(&axp->txq);    /* lose transmit queue */
  192.             drop_axr(axp);        /* drop ax25 route */
  193.             del_ax25(axp);      /* clean out the trash */
  194.         }
  195.         break;
  196.     case LAPB_SETUP:
  197.         switch(type){
  198.         case SABM:    /* Simultaneous open */
  199.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  200.             break;
  201.         case DISC:
  202.             sendctl(axp,LAPB_RESPONSE,DM|pf);
  203. #ifdef NETROM
  204.             nr_derate(axp);
  205. #endif
  206.             drop_axr(axp);      /* drop ax25 route */
  207.             free_q(&axp->txq);
  208.             stop_timer(&axp->t1);
  209.             axp->reason = LB_DM;
  210.             lapbstate(axp,LAPB_DISCONNECTED);
  211.             break;
  212.         case UA:    /* Connection accepted */
  213.             /* Note: xmit queue not cleared */
  214.             stop_timer(&axp->t1);
  215.             start_timer(&axp->t3);
  216.             axp->unack = axp->vr = axp->vs = 0;
  217.             lapbstate(axp,LAPB_CONNECTED);
  218.             start_timer(&axp->t4);
  219.             break;
  220.         case DM:    /* Connection refused */
  221.             free_q(&axp->txq);
  222.             stop_timer(&axp->t1);
  223.             axp->reason = LB_DM;
  224.             lapbstate(axp,LAPB_DISCONNECTED);
  225.             break;
  226.         default:    /* Respond with DM only to command polls */
  227.             if(poll)
  228.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  229.             break;
  230.         }
  231.         break;
  232.     case LAPB_DISCPENDING:
  233.         switch(type){
  234.         case SABM:
  235.             sendctl(axp,LAPB_RESPONSE,DM|pf);
  236.             drop_axr(axp);        /* drop ax25 route */
  237.             break;
  238.         case DISC:
  239.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  240.             drop_axr(axp);        /* drop ax25 route */
  241.             break;
  242.         case UA:
  243.         case DM:
  244.             stop_timer(&axp->t1);
  245.             lapbstate(axp,LAPB_DISCONNECTED);
  246.             break;
  247.         default:    /* Respond with DM only to command polls */
  248.             if(poll)
  249.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  250.             drop_axr(axp);        /* drop ax25 route */
  251.             break;
  252.         }
  253.         break;
  254.     case LAPB_CONNECTED:
  255.         switch(type){
  256.         case SABM:
  257.            sendctl(axp,LAPB_RESPONSE,UA|pf);
  258. #ifdef SABM_HOLDOFF
  259.            if (axp->flags.rxd_I_frame) {
  260.                 /* only reset if we've had a */
  261.                 /* valid I-frame. Otherwise he */
  262.                 /* may just not have got our UA */
  263. #endif
  264.                 clr_ex(axp);
  265.                 free_q(&axp->txq);
  266.                 stop_timer(&axp->t1);
  267.                 start_timer(&axp->t3);
  268.                 axp->unack = axp->vr = axp->vs = 0;
  269.                 lapbstate(axp,LAPB_CONNECTED); /* Purge queues */
  270. #ifdef SABM_HOLDOFF
  271.             }
  272. #endif
  273.             break;
  274.         case DISC:
  275.             free_q(&axp->txq);
  276.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  277.             stop_timer(&axp->t1);
  278.             stop_timer(&axp->t3);
  279.             axp->reason = LB_NORMAL;
  280.             lapbstate(axp,LAPB_DISCONNECTED);
  281.             break;
  282.         case DM:
  283.             axp->reason = LB_DM;
  284.             lapbstate(axp,LAPB_DISCONNECTED);
  285.             break;
  286.         case UA:
  287.             est_link(axp);
  288.             lapbstate(axp,LAPB_SETUP);    /* Re-establish */    
  289.             break;            
  290.         case FRMR:
  291.             est_link(axp);
  292.             lapbstate(axp,LAPB_SETUP);    /* Re-establish link */
  293.             break;
  294.         case RR:
  295.         case RNR:
  296.             axp->flags.remotebusy = (control == RNR) ? YES : NO;
  297.             if(poll)
  298.                 enq_resp(axp);
  299.             ackours(axp,nr);
  300.             break;
  301.         case REJ:
  302.             axp->flags.remotebusy = NO;
  303.             if(poll)
  304.                 enq_resp(axp);
  305.             ackours(axp,nr);
  306.             stop_timer(&axp->t1);
  307.             start_timer(&axp->t3);
  308.             /* This may or may not actually invoke transmission,
  309.              * depending on whether this REJ was caused by
  310.              * our losing his prior ACK.
  311.              */
  312.             inv_rex(axp);
  313.             break;    
  314.         case I:
  315.             ackours(axp,nr); /** == -1) */
  316. #ifdef SABM_HOLDOFF
  317.             axp->flags.rxd_I_frame = 1;   /* we got something */
  318. #endif
  319.             start_timer(&axp->t4);
  320.             if(len_p(axp->rxq) >= axp->window){
  321.                 /* Too bad he didn't listen to us; he'll
  322.                  * have to resend the frame later. This
  323.                  * drastic action is necessary to avoid
  324.                  * deadlock.
  325.                  */
  326.                 if(poll)
  327.                     sendctl(axp,LAPB_RESPONSE,RNR|pf);
  328.                 free_p(bp);
  329.                 bp = NULLBUF;
  330.                 break;
  331.             }
  332.             /* Reject or ignore I-frames with receive sequence number errors */
  333.             if(ns != axp->vr){
  334.                 if(axp->proto == V1 || !axp->flags.rejsent){
  335.                     axp->flags.rejsent = YES;
  336.                     sendctl(axp,LAPB_RESPONSE,REJ | pf);
  337.                 } else if(poll)
  338.                     enq_resp(axp);
  339.                 axp->response = 0;
  340.                 break;
  341.             }
  342.             axp->flags.rejsent = NO;
  343.             axp->vr = (axp->vr+1) & MMASK;
  344.             tmp = len_p(axp->rxq) >= axp->window ? RNR : RR;
  345.             if(poll){
  346.                 sendctl(axp,LAPB_RESPONSE,tmp|PF);
  347.             } else {
  348.                 axp->response = tmp;
  349.             }
  350.             procdata(axp,bp);
  351.             bp = NULLBUF;
  352.             break;
  353.         default:    /* All others ignored */
  354.             break;
  355.         }
  356.         break;
  357.     case LAPB_RECOVERY:
  358.         switch(type){
  359.         case SABM:
  360.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  361. #ifdef SABM_HOLDOFF
  362.            if (axp->flags.rxd_I_frame) {
  363.                 /* only reset if we've had a */
  364.                 /* valid I-frame. Otherwise he */
  365.                 /* may just not have got our UA */
  366. #endif
  367.                 clr_ex(axp);
  368.                 stop_timer(&axp->t1);
  369.                 start_timer(&axp->t3);
  370.                 axp->unack = axp->vr = axp->vs = 0;
  371.                 lapbstate(axp,LAPB_CONNECTED); /* Purge queues */
  372.                 if(!run_timer(&axp->t4))
  373.                     start_timer(&axp->t4);
  374. #ifdef SABM_HOLDOFF
  375.             }
  376. #endif
  377.             break;
  378.         case DISC:
  379.             free_q(&axp->txq);
  380.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  381.             stop_timer(&axp->t1);
  382.             stop_timer(&axp->t3);
  383.             axp->response = UA;
  384.             axp->reason = LB_NORMAL;
  385.             lapbstate(axp,LAPB_DISCONNECTED);
  386.             break;
  387.         case DM:
  388. #ifdef NETROM
  389.             nr_derate(axp);
  390. #endif
  391.             axp->reason = LB_DM;
  392.             lapbstate(axp,LAPB_DISCONNECTED);
  393.             break;
  394.         case UA:
  395.             est_link(axp);
  396.             lapbstate(axp,LAPB_SETUP);    /* Re-establish */    
  397.             break;
  398.         case FRMR:
  399.             est_link(axp);
  400.             lapbstate(axp,LAPB_SETUP);    /* Re-establish link */
  401.             break;
  402.         case RR:
  403.         case RNR:
  404.             axp->flags.remotebusy = (control == RNR) ? YES : NO;
  405.             if(axp->proto == V1 || final){
  406.                 stop_timer(&axp->t1);
  407.                 ackours(axp,nr);
  408.                 if(axp->unack != 0){
  409.                     inv_rex(axp);
  410.                 } else {
  411.                     start_timer(&axp->t3);
  412.                     lapbstate(axp,LAPB_CONNECTED);
  413.                     if(!run_timer(&axp->t4))
  414.                         start_timer(&axp->t4);
  415.                 }
  416.             } else {
  417.                 if(poll)
  418.                     enq_resp(axp);
  419.                 ackours(axp,nr);
  420.                 /* Keep timer running even if all frames
  421.                  * were acked, since we must see a Final
  422.                  */
  423.                 if(!run_timer(&axp->t1))
  424.                     start_timer(&axp->t1);
  425.             }
  426.             break;
  427.         case REJ:
  428.             axp->flags.remotebusy = NO;
  429.             /* Don't insist on a Final response from the old proto */
  430.             if(axp->proto == V1 || final){
  431.                 stop_timer(&axp->t1);
  432.                 ackours(axp,nr);
  433.                 if(axp->unack != 0){
  434.                     inv_rex(axp);
  435.                 } else {
  436.                     start_timer(&axp->t3);
  437.                     lapbstate(axp,LAPB_CONNECTED);
  438.                     if(!run_timer(&axp->t4))
  439.                         start_timer(&axp->t4);
  440.                 }
  441.             } else {
  442.                 if(poll)
  443.                     enq_resp(axp);
  444.                 ackours(axp,nr);
  445.                 if(axp->unack != 0){
  446.                     /* This is certain to trigger output */
  447.                     inv_rex(axp);
  448.                 }
  449.                 /* A REJ that acks everything but doesn't
  450.                  * have the F bit set can cause a deadlock.
  451.                  * So make sure the timer is running.
  452.                  */
  453.                 if(!run_timer(&axp->t1))
  454.                     start_timer(&axp->t1);
  455.             }
  456.             break;
  457.         case I:
  458.             ackours(axp,nr); /** == -1) */
  459. #ifdef SABM_HOLDOFF
  460.             axp->flags.rxd_I_frame = YES;   /* we got something */
  461. #endif
  462.             /* Make sure timer is running, since an I frame
  463.              * cannot satisfy a poll
  464.              */
  465.             if(!run_timer(&axp->t1))
  466.                 start_timer(&axp->t1);
  467.             if(len_p(axp->rxq) >= axp->window){
  468.                 /* Too bad he didn't listen to us; he'll
  469.                  * have to resend the frame later. This
  470.                  * drastic action is necessary to avoid
  471.                  * memory deadlock.
  472.                  */
  473.                 sendctl(axp,LAPB_RESPONSE,RNR | pf);
  474.                 free_p(bp);
  475.                 bp = NULLBUF;
  476.                 break;
  477.             }
  478.             /* Reject or ignore I-frames with receive sequence number errors */
  479.             if(ns != axp->vr){
  480.                 if(axp->proto == V1 || !axp->flags.rejsent){
  481.                     axp->flags.rejsent = YES;
  482.                     sendctl(axp,LAPB_RESPONSE,REJ | pf);
  483.                 } else if(poll)
  484.                     enq_resp(axp);
  485.  
  486.                 axp->response = 0;
  487.                 break;
  488.             }
  489.             axp->flags.rejsent = NO;
  490.             axp->vr = (axp->vr+1) & MMASK;
  491.             tmp = len_p(axp->rxq) >= axp->window ? RNR : RR;
  492.             if(poll){
  493.                 sendctl(axp,LAPB_RESPONSE,tmp|PF);
  494.             } else {
  495.                 axp->response = tmp;
  496.             }
  497.             procdata(axp,bp);
  498.             bp = NULLBUF;
  499.             break;
  500.         default:
  501.             break;        /* Ignored */
  502.         }
  503.         break;
  504.     }
  505.     free_p(bp);    /* In case anything's left */
  506.  
  507.     /* See if we can send some data, perhaps piggybacking an ack.
  508.      * If successful, lapb_output will clear axp->response.
  509.      */
  510.     lapb_output(axp);
  511.     if(axp->response != 0){
  512.         sendctl(axp,LAPB_RESPONSE,axp->response);
  513.         axp->response = 0;
  514.     }
  515.     return 0;
  516. }
  517.  
  518. /* Handle incoming acknowledgements for frames we've sent.
  519.  * Free frames being acknowledged.
  520.  * Return -1 to cause a frame reject if number is bad, 0 otherwise
  521.  */
  522. static int
  523. ackours(struct ax25_cb *axp, int16 n)
  524. {    
  525.     struct mbuf *bp;
  526.     int acked = 0;    /* Count of frames acked by this ACK */
  527.     int16 oldest;    /* Seq number of oldest unacked I-frame */
  528.     int32 rtt,abserr;
  529.  
  530.     /* Free up acknowledged frames by purging frames from the I-frame
  531.      * transmit queue. Start at the remote end's last reported V(r)
  532.      * and keep going until we reach the new sequence number.
  533.      * If we try to free a null pointer,
  534.      * then we have a frame reject condition.
  535.      */
  536.     oldest = (axp->vs - axp->unack) & MMASK;
  537.     while(axp->unack != 0 && oldest != n){
  538.         if((bp = dequeue(&axp->txq)) == NULLBUF){
  539.             /* Acking unsent frame */
  540.             return -1;
  541.         }
  542.         free_p(bp);
  543.         axp->unack--;
  544.         acked++;
  545.         if(axp->flags.rtt_run && axp->rtt_seq == oldest){
  546.             /* A frame being timed has been acked */
  547.             axp->flags.rtt_run = 0;
  548.             /* Update only if frame wasn't retransmitted */
  549.             if(!axp->flags.retrans){
  550.                 rtt = msclock() - axp->rtt_time;
  551.                 abserr = (rtt > axp->srt) ? rtt - axp->srt :
  552.                  axp->srt - rtt;
  553.  
  554.                 /* Run SRT and mdev integrators */
  555.                 axp->srt = ((axp->srt * 7) + rtt + 4) >> 3;
  556.                 axp->mdev = ((axp->mdev*3) + abserr + 2) >> 2;
  557.                 /* Update timeout */
  558.                 set_timer(&axp->t1,4*axp->mdev+axp->srt);
  559.             }
  560.         }
  561.         axp->flags.retrans = 0;
  562.         axp->retries = 0;
  563.         oldest = (oldest + 1) & MMASK;
  564.     }
  565.     if(axp->unack == 0){
  566.         /* All frames acked, stop timeout */
  567.         stop_timer(&axp->t1);
  568.         start_timer(&axp->t3);
  569.     } else if(acked != 0) {
  570.         /* Partial ACK; restart timer */
  571.         start_timer(&axp->t1);
  572.     }
  573.     if(acked != 0){
  574.         /* If user has set a transmit upcall, indicate how many frames
  575.          * may be queued
  576.          */
  577.         if(axp->t_upcall != NULLVFP)
  578.             (*axp->t_upcall)(axp,axp->paclen * (axp->maxframe - axp->unack));
  579.     }
  580.     return 0;
  581. }
  582.  
  583. /* Establish data link */
  584. void
  585. est_link(axp)
  586. struct ax25_cb *axp;
  587. {
  588.     clr_ex(axp);
  589.     axp->retries = 0;
  590.     sendctl(axp,LAPB_COMMAND,SABM|PF);
  591.     stop_timer(&axp->t3);
  592.     start_timer(&axp->t1);
  593. }
  594. /* Clear exception conditions */
  595. static void
  596. clr_ex(axp)
  597. struct ax25_cb *axp;
  598. {
  599.     axp->flags.remotebusy = NO;
  600.     axp->flags.rejsent = NO;
  601.     axp->response = 0;
  602.     stop_timer(&axp->t3);
  603. }
  604. /* Enquiry response */
  605. static void
  606. enq_resp(axp)
  607. struct ax25_cb *axp;
  608. {
  609.     char ctl;
  610.  
  611.     ctl = len_p(axp->rxq) >= axp->window ? RNR|PF : RR|PF;    
  612.     sendctl(axp,LAPB_RESPONSE,ctl);
  613.     axp->response = 0;
  614.     stop_timer(&axp->t3);
  615. }
  616. /* Invoke retransmission */
  617. static void
  618. inv_rex(axp)
  619. struct ax25_cb *axp;
  620. {
  621.     axp->vs -= axp->unack;
  622.     axp->vs &= MMASK;
  623.     axp->unack = 0;
  624. }
  625. /* Send S or U frame to currently connected station */
  626. int
  627. sendctl(axp,cmdrsp,cmd)
  628. struct ax25_cb *axp;
  629. int cmdrsp;
  630. int cmd;
  631. {
  632.     if((ftype((char)cmd) & 0x3) == S)    /* Insert V(R) if S frame */
  633.         cmd |= (axp->vr << 5);
  634.     return sendframe(axp,cmdrsp,cmd,NULLBUF);
  635. }
  636. /* Start data transmission on link, if possible
  637.  * Return number of frames sent
  638.  */
  639. int
  640. lapb_output(axp)
  641. register struct ax25_cb *axp;
  642. {
  643.     register struct mbuf *bp;
  644.     struct mbuf *tbp;
  645.     char control;
  646.     int sent = 0;
  647.     int i;
  648.  
  649.     if(axp == NULLAX25
  650.      || (axp->state != LAPB_RECOVERY && axp->state != LAPB_CONNECTED)
  651.      || axp->flags.remotebusy)
  652.         return 0;
  653.  
  654.     /* Dig into the send queue for the first unsent frame */
  655.     bp = axp->txq;
  656.     for(i = 0; i < axp->unack; i++){
  657.         if(bp == NULLBUF)
  658.             break;    /* Nothing to do */
  659.         bp = bp->anext;
  660.     }
  661.     /* Start at first unsent I-frame, stop when either the
  662.      * number of unacknowledged frames reaches the maxframe limit,
  663.      * or when there are no more frames to send
  664.      */
  665.     while(bp != NULLBUF && axp->unack < axp->maxframe){
  666.         control = I | (axp->vs++ << 1) | (axp->vr << 5);
  667.         axp->vs &= MMASK;
  668.         dup_p(&tbp,bp,0,len_p(bp));
  669.         if(tbp == NULLBUF)
  670.             return sent;    /* Probably out of memory */
  671.         sendframe(axp,LAPB_COMMAND,control,tbp);
  672.         start_timer(&axp->t4);
  673.         axp->unack++;
  674.         /* We're implicitly acking any data he's sent, so stop any
  675.          * delayed ack
  676.          */
  677.         axp->response = 0;
  678.         if(!run_timer(&axp->t1)){
  679.             stop_timer(&axp->t3);
  680.             start_timer(&axp->t1);
  681.         }
  682.         sent++;
  683.         bp = bp->anext;
  684.         if(!axp->flags.rtt_run){
  685.             /* Start round trip timer */
  686.             axp->rtt_seq = (control >> 1) & MMASK;
  687.             axp->rtt_time = msclock();
  688.             axp->flags.rtt_run = 1;
  689.         }
  690.     }
  691.     return sent;
  692. }
  693. /* Set new link state */
  694. void
  695. lapbstate(axp,s)
  696. struct ax25_cb *axp;
  697. int s;
  698. {
  699.     int oldstate;
  700.  
  701.     oldstate = axp->state;
  702.     axp->state = s;
  703.     if(s == LAPB_DISCONNECTED){
  704.         stop_timer(&axp->t1);
  705.         stop_timer(&axp->t3);
  706.         stop_timer(&axp->t4);
  707.         free_q(&axp->txq);
  708.         drop_axr(axp);        /* any ax25 route that hasn't been dropped yet*/
  709.     }
  710.     /* Don't bother the client unless the state is really changing */
  711.     if((oldstate != s) && (axp->s_upcall != NULLVFP))
  712.         (*axp->s_upcall)(axp,oldstate,s);
  713. }
  714. /* Process a valid incoming I frame */
  715. static void
  716. procdata(axp,bp)
  717. struct ax25_cb *axp;
  718. struct mbuf *bp;
  719. {
  720.     int pid;
  721.     int seq;
  722.  
  723.     /* Extract level 3 PID */
  724.     if((pid = PULLCHAR(&bp)) == -1)
  725.         return;    /* No PID */
  726.  
  727.     if(axp->segremain != 0){
  728.         /* Reassembly in progress; continue */
  729.         seq = PULLCHAR(&bp);
  730.         if(pid == PID_SEGMENT
  731.          && (seq & SEG_REM) == axp->segremain - 1){
  732.             /* Correct, in-order segment */
  733.             append(&axp->rxasm,bp);
  734.             if((axp->segremain = (seq & SEG_REM)) == 0){
  735.                 /* Done; kick it upstairs */
  736.                 bp = axp->rxasm;
  737.                 axp->rxasm = NULLBUF;
  738.                 pid = PULLCHAR(&bp);
  739.                 handleit(axp,pid,bp);
  740.             }
  741.         } else {
  742.             /* Error! */
  743.             free_p(axp->rxasm);
  744.             axp->rxasm = NULLBUF;
  745.             axp->segremain = 0;
  746.             free_p(bp);
  747.         }
  748.     } else {
  749.         /* No reassembly in progress */
  750.         if(pid == PID_SEGMENT){
  751.             /* Start reassembly */
  752.             seq = PULLCHAR(&bp);
  753.             if(!(seq & SEG_FIRST)){
  754.                 free_p(bp);    /* not first seg - error! */
  755.             } else {
  756.                 /* Put first segment on list */
  757.                 axp->segremain = seq & SEG_REM;
  758.                 axp->rxasm = bp;
  759.             }
  760.         } else {
  761.             /* Normal frame; send upstairs */
  762.             handleit(axp,pid,bp);
  763.         }
  764.     }
  765. }
  766. /* New-style frame segmenter. Returns queue of segmented fragments, or
  767.  * original packet if small enough
  768.  */
  769. struct mbuf *
  770. segmenter(struct mbuf *bp, int16 ssize)
  771. {
  772.     struct mbuf *result = NULLBUF;
  773.     struct mbuf *bptmp,*bp1;
  774.     int16 len,offset;
  775.     int segments;
  776.  
  777.     /* See if packet is too small to segment. Note 1-byte grace factor
  778.      * so the PID will not cause segmentation of a 256-byte IP datagram.
  779.      */
  780.     len = len_p(bp);
  781.     if(len <= ssize+1)
  782.         return bp;    /* Too small to segment */
  783.  
  784.     ssize -= 2;        /* ssize now equal to data portion size */
  785.     segments = 1 + (len - 1) / ssize;    /* # segments  */
  786.     offset = 0;
  787.  
  788.     while(segments != 0){
  789.         offset += dup_p(&bptmp,bp,offset,ssize);
  790.         if(bptmp == NULLBUF){
  791.             free_q(&result);
  792.             break;
  793.         }
  794.         /* Make room for segmentation header */
  795.         if((bp1 = pushdown(bptmp,2)) == NULLBUF){
  796.             free_p(bptmp);
  797.             free_q(&result);
  798.             break;
  799.         }
  800.         bp1->data[0] = PID_SEGMENT;
  801.         bp1->data[1] = --segments;
  802.         if(offset == ssize)
  803.             bp1->data[1] |= SEG_FIRST;
  804.         enqueue(&result,bp1);
  805.     }
  806.     free_p(bp);
  807.     return result;
  808. }
  809.  
  810. static void
  811. handleit(axp,pid,bp)
  812. struct ax25_cb *axp;
  813. int pid;
  814. struct mbuf *bp;
  815. {
  816.     struct axlink *ipp;
  817.  
  818.     for(ipp = Axlink;ipp->funct != NULL;ipp++){
  819.         if(ipp->pid == pid)
  820.             break;
  821.     }
  822.     if(ipp->funct != NULL)
  823.         (*ipp->funct)(axp->iface,axp,NULLCHAR,NULLCHAR,bp,0);
  824.     else
  825.         free_p(bp);
  826. }
  827.  
  828. #endif /* AX25 */
  829.  
  830.